package chapt01.block;

public class M3D
{
	//////////////////////////////////////////////////////////////////////////////////////
	// Cross Product
	// u x v = result
	// 3 component vectors only.
	static void crossProduct3(float result[], float u[], float v[])
	{
		result[0] = u[1]*v[2] - v[1]*u[2];
		result[1] = -u[0]*v[2] + v[0]*u[2];
		result[2] = u[0]*v[1] - v[0]*u[1];
	}
	
	//////////////////////////////////////////////////////////////////////////////////////
	// Normalize a vector
	// Scale a vector to unit length. Easy, just scale the vector by it's length
	static void normalizeVector3(float u[])
	{
		scaleVector3(u, 1.0f / getVectorLength3(u));
	}

	//////////////////////////////////////////////////////////////////////////////////////
	// Get length of vector
	// Only for three component vectors.
	static float getVectorLength3(float u[])
	{
		return (float)Math.sqrt(getVectorLengthSquared3(u));
	}
	
	// Only for three component vectors
	static float getVectorLengthSquared3(float u[])
	{
		return (u[0] * u[0]) + (u[1] * u[1]) + (u[2] * u[2]);
	}
	
	///////////////////////////////////////////////////////////////////////////////////////
	// Scale Vectors (in place)
	static void scaleVector3(float v[], float scale) 
	{
		v[0] *= scale; v[1] *= scale; v[2] *= scale;
	}
	
	////////////////////////////////////////////////////////////////////////////////////////
	// Calculate the plane equation of the plane that the three specified points lay in. The
	// points are given in clockwise winding order, with normal pointing out of clockwise face
	// planeEq contains the A,B,C, and D of the plane equation coefficients
	static void getPlaneEquation(float planeEq[], float p1[], float p2[], float p3[])
	{
	    // Get two vectors... do the cross product
	    float v1[] = new float[4];
	    float v2[] = new float[4];

	    // V1 = p3 - p1
	    v1[0] = p3[0] - p1[0];
	    v1[1] = p3[1] - p1[1];
	    v1[2] = p3[2] - p1[2];

	    // V2 = P2 - p1
	    v2[0] = p2[0] - p1[0];
	    v2[1] = p2[1] - p1[1];
	    v2[2] = p2[2] - p1[2];

	    // Unit normal to plane - Not sure which is the best way here
	    crossProduct3(planeEq, v1, v2);
	    normalizeVector3(planeEq);

	    // Back substitute to get D
	    planeEq[3] = -(planeEq[0] * p3[0] + planeEq[1] * p3[1] + planeEq[2] * p3[2]);
	}
	
	///////////////////////////////////////////////////////////////////////////
	// Create a projection to "squish" an object into the plane.
	// Use m3dGetPlaneEquationf(planeEq, point1, point2, point3);
	// to get a plane equation.
	static void makePlanarShadowMatrix(float proj[], float planeEq[], float vLightPos[])
	{
		// These just make the code below easier to read. They will be 
		// removed by the optimizer.	
		float a = planeEq[0];
		float b = planeEq[1];
		float c = planeEq[2];
		float d = planeEq[3];

		float dx = -vLightPos[0];
		float dy = -vLightPos[1];
		float dz = -vLightPos[2];

		// Now build the projection matrix
		proj[0] = b * dy + c * dz;
		proj[1] = -a * dy;
		proj[2] = -a * dz;
		proj[3] = 0.0f;

		proj[4] = -b * dx;
		proj[5] = a * dx + c * dz;
		proj[6] = -b * dz;
		proj[7] = 0.0f;

		proj[8] = -c * dx;
		proj[9] = -c * dy;
		proj[10] = a * dx + b * dy;
		proj[11] = 0.0f;

		proj[12] = -d * dx;
		proj[13] = -d * dy;
		proj[14] = -d * dz;
		proj[15] = a * dx + b * dy + c * dz;
		// Shadow matrix ready
	}
}
